package com.ruoyi.web.controller.aspectj;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.ruoyi.common.utils.ip.IpUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.bouncycastle.asn1.ocsp.ResponseData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;

//@Component
//@Aspect
//@Order(-1)
public class LogEventTrackingAspect {

    private final Logger logger = LoggerFactory.getLogger(LogEventTrackingAspect.class);




    @Pointcut("execution (* com.ruoyi.web.controller.*.*.*(..))")
    public void requestServer() {

    }

    @Around("requestServer()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        //记录请求开始执行时间
        long beginTime = System.currentTimeMillis();



        //获取请求参数
        ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = sra.getRequest();

        //获取代理地址、请求地址、请求类名、方法名
        String remoteAddress = IpUtils.getIpAddr(request);
        String requestURI = request.getRequestURI();
        String methodName = pjp.getSignature().getName();
        //String clazzName = pjp.getTarget().getClass().getSimpleName();

        //获取请求参数
        MethodSignature ms = (MethodSignature) pjp.getSignature();
        //获取请求参数类型
        String[] parameterNames = ms.getParameterNames();
        //获取请求参数值
        Object[] parameterValues = pjp.getArgs();
        StringBuilder sb = new StringBuilder();
        //组合请求参数，进行日志打印
        if (parameterNames != null && parameterNames.length > 0) {
            for (int i = 0; i < parameterNames.length; i++) {
                if (requestURI.toLowerCase().contains("ocr")) {
                    break;
                }
                if (parameterNames[i].equals("bindingResult")) {
                    break;
                }
                if ((parameterValues[i] instanceof HttpServletRequest) || (parameterValues[i] instanceof HttpServletResponse)
                        || (parameterValues[i] instanceof MultipartFile)
                        || (parameterValues[i] instanceof StandardMultipartHttpServletRequest)) {
                    sb.append("[")
                            .append(parameterNames[i]).append("=").append(parameterValues[i])
                            .append("]");
                } else {
                    String params = JSON.toJSONString(parameterValues[i], SerializerFeature.WriteDateUseDateFormat);
//                    if (parameterValues[i] instanceof CgUserPwdLoginParam) {
//                        CgUserPwdLoginParam pwdLoginParams = (CgUserPwdLoginParam) parameterValues[i];
//                        CgUserPwdLoginParam loginParam = BeanUtil.copyProperties(pwdLoginParams, CgUserPwdLoginParam.class);
//                        loginParam.setPassWord(null);
//                        params = JSON.toJSONString(loginParam, SerializerFeature.WriteDateUseDateFormat);
//                    }
                    sb.append("[")
                            .append(parameterNames[i]).append("=")
                            .append(params)
                            .append("]");
                }
            }
        }
        //获取接口名注释
        Api api = (Api) pjp.getSignature().getDeclaringType().getAnnotation(Api.class);
        String apiName = ObjectUtil.isNotEmpty(api) ? CollectionUtil.isNotEmpty(Arrays.asList(api.tags())) ? api.tags()[0] : api.value() : StrUtil.EMPTY;
        ApiOperation apiOperation = ms.getMethod().getAnnotation(ApiOperation.class);
        String apiOperationName = ObjectUtil.isNotEmpty(apiOperation) ? apiOperation.value() : StrUtil.EMPTY;
        Object result = null;
//        //保存操作日志
//        try {
//            String url = request.getRequestURL().toString();
//            if (StrUtil.isNotBlank(url) && url.contains(".com")) {
//                url = url.replace(".com", ".com/yk");
//            }
//            UserModel user = UserTokenUtil.getUser();
//            String operatorName = null;
//            String operatorPhone = null;
//            Long userId = null;
//            if (ObjectUtil.isNotEmpty(user)) {
//                operatorName = user.getUserName();
//                operatorPhone = user.getLoginName();
//                userId = user.getUserId();
//            }
//            CommOperateLogModel logModel = new CommOperateLogModel().setRequestUrl(url).setRequestParams(sb.toString())
//                    .setOperatorName(operatorName).setOperatorPhone(operatorPhone).setIp(remoteAddress).setTraceId(traceId)
//                    .setSource(CommOperateLogSourceEnum.USER.getValue());
//            logModel.setCreateBy(userId);
//            commOperateLogBizService.save(logModel);
//        } catch (Exception e) {
//
//        }
        try {
            result = pjp.proceed();
        } catch (Throwable throwable) {
            //记录请求完成执行时间
            long endTime = System.currentTimeMillis();
            long usedTime = endTime - beginTime;
            logger.error("|err|{}|{}|{}|{}|{}|{}|{}|{}|{}|{}|{}|{}|", DateUtil.now(),
                     remoteAddress, usedTime, apiName, apiOperationName, requestURI, methodName, sb, null, null, null);
            throw throwable;
        }
        //请求操作成功
        String resultJsonString = "";
        if (result != null) {
            if (result instanceof ResponseData) {
                resultJsonString = JSON.toJSONString(result, SerializerFeature.WriteDateUseDateFormat);
            } else {
                resultJsonString = String.valueOf(result);
            }
            if (requestURI.toLowerCase().contains("/api/v1/login")) {
                JSONObject jsonObject = JSONUtil.parseObj(result);
                jsonObject.set("data", null);
                resultJsonString = JSONUtil.toJsonStr(jsonObject);
            }
        }
        //记录请求完成执行时间
        long endTime = System.currentTimeMillis();
        long usedTime = endTime - beginTime;
        //记录日志
        // 时间|TID|请求IP|请求耗时|请求URI|请求方法|请求参数列表|返回结果|错误码（正常则无）|异常信息（正常则无）|
        logger.info("|info|{}|{}|{}|{}|{}|{}|{}|{}|{}|{}|{}|{}|", DateUtil.now(),
              remoteAddress, usedTime, apiName, apiOperationName, requestURI, methodName, sb, null, null);
        return result;
    }
}
